package tech.xiaozai.rbac.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.xiaozai.rbac.bo.MenuBO;
import tech.xiaozai.rbac.bo.PermissionBO;
import tech.xiaozai.rbac.mapper.SysPermissionMapper;
import tech.xiaozai.rbac.mapper.SysRolePermissionRelationMapper;
import tech.xiaozai.rbac.mapstruct.MenuMapStruct;
import tech.xiaozai.rbac.mapstruct.PermissionMapStruct;
import tech.xiaozai.rbac.po.SysPermission;
import tech.xiaozai.rbac.po.SysPermissionExample;
import tech.xiaozai.rbac.po.SysRolePermissionRelationExample;
import tech.xiaozai.rbac.po.SysRolePermissionRelationKey;

import java.util.*;

/**
 * @author xiaozai
 * @version 1.0
 * @date 2020-09-21 09:43
 */

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private SysPermissionMapper permissionMapper;

    @Autowired
    private SysRolePermissionRelationMapper rolePermissionRelationMapper;

    @Override
    public List<MenuBO> getMenus(List<String> roleIds) {

        //如果没有角色信息传进来，则也没有权限，就没有菜单
        if(roleIds==null || roleIds.isEmpty()){
            return null;
        }

        List<Long> rids = roleIds.stream().mapToLong(rid -> Long.parseLong(rid)).collect(ArrayList::new, List::add, List::addAll);
        SysRolePermissionRelationExample examplex = new SysRolePermissionRelationExample();
        examplex.createCriteria().andRidIn(rids);
        List<SysRolePermissionRelationKey> keys = rolePermissionRelationMapper.selectByExample(examplex);
        //角色如何查不到权限，不给菜单
        if(keys==null || keys.isEmpty()){
            return null;
        }
        List<Long> pids = keys.stream().mapToLong(key -> key.getPid()).collect(ArrayList::new, List::add, List::addAll);
        SysPermissionExample example = new SysPermissionExample();
        example.createCriteria().andTypEqualTo((byte) 1).andStateEqualTo((byte) 1).andIdIn(pids);

        List<SysPermission> menuPOS = permissionMapper.selectByExample(example);
        //如果一个菜单都没有,直接返回空
        if (menuPOS.isEmpty()) {
            return null;
        }

        List<MenuBO> menuBOS = MenuMapStruct.me.toBoList(menuPOS);

        Map<Long, MenuBO> map = new HashMap<>();
        //将bo放进map,以其id为key,bo为value
        menuBOS.forEach(bo -> map.put(bo.getId(), bo));

        //构建它们的父子关系
        map.values().forEach(bo -> {
            MenuBO parent = map.get(bo.getPid());
            if (parent != null) {
                if (parent.getChildren() == null) {
                    parent.setChildren(new LinkedList<>());
                }
                parent.getChildren().add(bo);
            }
        });

        //将Menu以sort字段排序
        map.values().forEach(bo -> {
            if (bo.getChildren() != null) {
                //Comparator接口
//                bo.getChildren().sort((b1,b2)->b1.getSort()-b2.getSort());
                bo.getChildren().sort(Comparator.comparingInt(MenuBO::getSort));
            }
        });

        //从map中拿顶级菜单列表, 关键语法就是Java8的Stream设施
        return map.values().stream().filter(bo -> bo.getPid() == 0)
                .sorted(Comparator.comparingInt(MenuBO::getSort))
                .collect(LinkedList::new, List::add, List::addAll);
    }

    @Override
    public List<PermissionBO> getAllPermissions() {

        List<SysPermission> sysPermissions = permissionMapper.selectByExample(null);
        List<PermissionBO> permissionBOS = PermissionMapStruct.me.toBoList(sysPermissions);
        Map<Long, PermissionBO> map = new HashMap<>();
        permissionBOS.forEach(bo -> map.put(bo.getId(), bo));

        //构建它们的父子关系
        map.values().forEach(bo -> {
            PermissionBO parent = map.get(bo.getPid());
            if (parent != null) {
                if (parent.getChildren() == null) {
                    parent.setChildren(new LinkedList<>());
                }
                parent.getChildren().add(bo);
            }
        });

        //将Permission以sort字段排序
        map.values().forEach(bo -> {
            if (bo.getChildren() != null) {
                bo.getChildren().sort(Comparator.comparingInt(PermissionBO::getSort));
            }
        });

        //从map中拿顶级菜单列表, 关键语法就是Java8的Stream设施
        return map.values().stream().filter(bo -> bo.getPid() == 0)
                .sorted(Comparator.comparingInt(PermissionBO::getSort))
                .collect(LinkedList::new, List::add, List::addAll);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePermission(PermissionBO permission) {
        List<PermissionBO> permissions = getAllPermissions();

        PermissionBO root = findTreeRoot(permissions, permission.getId());
        if (root == null) {
            return;
        }
        //如果有状态字段要更新，且本节点有子节点，则要递归处理子节点
        if (permission.getState() != null && root.getChildren() != null) {

            //收集各级子节点的ID列表
            List<Long> childrenIds = new LinkedList<>();
            collectChildrenIds(root, childrenIds);
            SysPermission record = new SysPermission();
            record.setState(permission.getState());
            SysPermissionExample example = new SysPermissionExample();
            example.createCriteria().andIdIn(childrenIds);
            permissionMapper.updateByExampleSelective(record, example);
        }

        SysPermission self = PermissionMapStruct.me.toPo(permission);
        permissionMapper.updateByPrimaryKeySelective(self);
    }

    @Override
    public List<Long> getAllPermissionLeafIds() {
        List<SysPermission> sysPermissions = permissionMapper.selectByExample(null);
        List<Long> pids = sysPermissions.stream().mapToLong(v -> v.getPid()).collect(LinkedList::new, List::add, List::addAll);
        SysPermissionExample example = new SysPermissionExample();
        example.createCriteria().andIdNotIn(pids);
        List<SysPermission> leaves = permissionMapper.selectByExample(example);
        if (leaves != null && !leaves.isEmpty()) {
            return leaves.stream().mapToLong(v -> v.getId()).collect(LinkedList::new, List::add, List::addAll);
        }
        return null;
    }

    @Override
    public List<Long> getPermissionIdsOfRole(Long roleId) {
        SysRolePermissionRelationExample example = new SysRolePermissionRelationExample();
        example.createCriteria().andRidEqualTo(roleId);
        List<SysRolePermissionRelationKey> keys = rolePermissionRelationMapper.selectByExample(example);
        if (keys != null && !keys.isEmpty()) {
            return keys.stream().mapToLong(v -> v.getPid()).collect(LinkedList::new, List::add, List::addAll);
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePermissionsOfRole(Long roleId, List<Long> permissionIds) {
        SysRolePermissionRelationExample example = new SysRolePermissionRelationExample();
        example.createCriteria().andRidEqualTo(roleId);
        List<SysRolePermissionRelationKey> keys = rolePermissionRelationMapper.selectByExample(example);
        List<Long> oldPids = keys.stream().mapToLong(k -> k.getPid()).collect(LinkedList::new, List::add, List::addAll);

        List<Long> needDelete = new LinkedList<>(oldPids);
        needDelete.removeAll(permissionIds);
        //删
        if (!needDelete.isEmpty()) {
            SysRolePermissionRelationExample example2 = new SysRolePermissionRelationExample();
            example2.createCriteria().andRidEqualTo(roleId).andPidIn(needDelete);
            rolePermissionRelationMapper.deleteByExample(example2);
        }

        permissionIds.removeAll(oldPids);

        //添
        if (!permissionIds.isEmpty()) {
            SysRolePermissionRelationKey newKey = new SysRolePermissionRelationKey();
            newKey.setRid(roleId);
            permissionIds.forEach(pid -> {
                newKey.setPid(pid);
                rolePermissionRelationMapper.insertSelective(newKey);
            });
        }
    }

    private void collectChildrenIds(PermissionBO root, List<Long> childrenIds) {
        if (root.getChildren() != null) {
            root.getChildren().forEach(child -> {
                //收集子节点的ID
                childrenIds.add(child.getId());

                //如果子节点还有子节点，则递归调用收集函数
                if (child.getChildren() != null) {
                    collectChildrenIds(child, childrenIds);
                }
            });
        }
    }


    private PermissionBO findTreeRoot(List<PermissionBO> forest, Long id) {
        for (PermissionBO bo : forest) {
            if (bo.getId().equals(id)) {
                return bo;
            }
            if (bo.getChildren() != null) {
                PermissionBO root = findTreeRoot(bo.getChildren(), id);
                if (root != null) {
                    return root;
                }
            }
        }
        return null;
    }


    //  下边的代码采用递归来处理更新子树，但会引起sql语句井喷
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public void updatePermission(PermissionBO permission) {
//
//        //本节点
//        SysPermission sysPermission = PermissionMapStruct.me.toPo(permission);
//
//        if( sysPermission.getState()!=null) {
//            SysPermission record = new SysPermission();
//            record.setState(permission.getState());
//            updateChildrenOf(sysPermission.getId(), record);
//        }
//        permissionMapper.updateByPrimaryKeySelective(sysPermission);
//    }
//
//    public void updateChildrenOf(Long id,SysPermission record){
//        SysPermissionExample example = new SysPermissionExample();
//        example.createCriteria().andPidEqualTo(id);
//        List<SysPermission> children = permissionMapper.selectByExample(example);
//        if(children!=null) {
//            children.forEach(child -> updateChildrenOf(child.getId(),record));
//        }
//        permissionMapper.updateByExampleSelective(record, example);
//
//    }
}
